home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-04 / dm3_src.zip / DMTIMEIO.ASM < prev    next >
Assembly Source File  |  1990-01-10  |  15KB  |  471 lines

  1.  
  2. ;* ************************************************************************* *;
  3. ;*                                                                           *;
  4. ;*       I B M - P C   R E A L   T I M E   C L O C K   R O U T I N E S       *;
  5. ;*                                                                           *;
  6. ;* ************************************************************************* *;
  7.  
  8.  
  9. ;==========================
  10. ;     Data Structure
  11. ;       Definitions
  12. ;==========================
  13.  
  14. DMTIME          struc
  15. ;
  16. ttype           dw      0               ; Timer type
  17.                                         ; 0 = Multiple Event Interval Timer
  18.                                         ; 1 = Single Event Countdown Timer
  19. counter         dw      0               ; Tick Counter
  20. interval        dw      0               ; Interval or Countdown Value
  21. event           dw      0               ; Event Flag/Counter
  22. link            dd      0               ; Link to next timer
  23. ;
  24. DMTIME          ends
  25.  
  26.  
  27. ;==========================
  28. ;      DOS Interface
  29. ;       Definitions
  30. ;==========================
  31.  
  32. TIMER_VECTOR    equ     08H             ; Interval Timer Interrupt Number
  33.  
  34. DOS             equ     21H             ; DOS access vector
  35.  
  36. DOS_SET_VECTOR  equ     25H             ; Set interrupt vector
  37. DOS_GET_VECTOR  equ     35H             ; Get interrupt vector
  38.  
  39.  
  40. ;==========================
  41. ;      Timer Monitor
  42. ;     For DM Library
  43. ;==========================
  44.  
  45. DMIOSEG SEGMENT 'CODE'
  46. ASSUME  cs:DMIOSEG
  47.  
  48.  
  49. ;==========================
  50. ;    Linkage References
  51. ;==========================
  52.  
  53. public  _dmtimer_init
  54. public  _dmtimer_release
  55. public  _dmtimer_add
  56. public  _dmtimer_sub
  57.  
  58.  
  59. ;==========================
  60. ;       Local Storage
  61. ;==========================
  62.  
  63. timer_table     label   word            ; 1/10 of second flags
  64.         db      0,1,0,1,0,1,0,1,0,1
  65.         db      1,0,1,0,1,0,1,0,1,0
  66.         db      1,1,0,1,0,1,0,1,0,1
  67.         db      0,1,1,0,1,0,1,0,1,0
  68.         db      1,0,1,1,0,1,0,1,0,1
  69.         db      0,1,0,1,1,0,1,0,1,0
  70.         db      1,0,1,0,1,1,0,1,0,1
  71.         db      0,1,0,1,0,1,1,0,1,0
  72.         db      1,0,1,0,1,0,1,1,0,1
  73.         db      1
  74.  
  75. oldint  dw      offset _dmtimer_isr     ; Old interrupt vector
  76.         dw      seg _dmtimer_isr
  77.  
  78. timer_tick      dw      0               ; Tick counter
  79. root_timer      label   word            ; Root timer
  80.         DMTIME  <0, 0, 1, 0, 0>
  81.  
  82.  
  83. ;==========================
  84. ;      Code Section
  85. ;==========================
  86.  
  87. _dmtimer_init   proc    far
  88. ;
  89. ;==========================
  90. ;   Timer Initialization
  91. ;==========================
  92. ; Procedure:    1. Save the passed parameters
  93. ;               2. Init flags & pointers
  94. ;               3. Save old interrupt vectors
  95. ;               4. Set new vectors
  96. ;               5. Exit all done
  97. ; Entry:        None
  98. ; Return:       AX = -1 if error
  99. ;               AX =  0 if init processed ok
  100. ;
  101.  
  102. ;
  103. ; Access the stack frame
  104. ;
  105.         push    bp                      ; save c stack frame
  106.         mov     bp,sp
  107.         push    es                      ; save environment
  108.         push    ds
  109.         push    di
  110.         push    si
  111.         mov     ax,cs                   ; point to data
  112.         mov     ds,ax
  113. ;
  114. ; Init the clock & root timer
  115. ;
  116.         mov     timer_tick,0            ; current tick value
  117.         lea     si,root_timer           ; point to the timer
  118.         mov     word ptr [si.ttype],0   ; type is interval timer
  119.         mov     word ptr [si.counter],0 ; counter is at 0
  120.         mov     word ptr [si.interval],1 ; interval is 1 tick
  121.         mov     word ptr [si.event],0   ; no events thus far
  122.         mov     word ptr [si.link],0    ; no other timers right now
  123.         mov     word ptr [si.link+2],0
  124. ;
  125. ; Save int vector
  126. ;
  127.         mov     ah,DOS_GET_VECTOR       ; Save original interrupt vectors
  128.         mov     al,TIMER_VECTOR
  129.         int     DOS
  130.         mov     word ptr oldint,bx
  131.         mov     word ptr oldint+2,es
  132. ;
  133. ; Redirect ints to ISR
  134. ;
  135.         push    ds
  136.         mov     ax,SEG _dmtimer_isr
  137.         mov     ds,ax
  138.         mov     dx,OFFSET _dmtimer_isr
  139.         mov     ah,DOS_SET_VECTOR       ; Set new interrupt vectors
  140.         mov     al,TIMER_VECTOR
  141.         int     DOS
  142.         pop     ds
  143. ;
  144. ; Exit all done
  145. ;
  146.         pop     si                      ; restore registers
  147.         pop     di
  148.         pop     ds
  149.         pop     es
  150.         pop     bp                      ; clear out stack frame
  151.         ret
  152. ;
  153. _dmtimer_init   endp
  154.  
  155.  
  156. _dmtimer_release proc   far
  157. ;
  158. ;==========================
  159. ;      Timer Release
  160. ;==========================
  161. ; Procedure:    1. Restore old INT vector
  162. ;               2. Exit all done
  163. ; Entry:        None
  164. ; Return:       None
  165. ;
  166.         push    es                      ; Save
  167.         push    ds
  168.         push    di
  169.         push    si
  170.         mov     ax,cs                   ; Access local storage
  171.         mov     ds,ax
  172. ;
  173. ; Restore int vector
  174. ;
  175.         mov     dx,word ptr [oldint]
  176.         mov     bx,word ptr [oldint+2]
  177.         mov     ah,DOS_SET_VECTOR       ; Save original interrupt vectors
  178.         mov     al,TIMER_VECTOR
  179.         mov     ds,bx
  180.         int     DOS
  181. ;
  182. ; Exit all done
  183. ;
  184.         pop     si                      ; restore registers
  185.         pop     di
  186.         pop     ds
  187.         pop     es
  188.         ret
  189. ;
  190. _dmtimer_release endp
  191.  
  192.  
  193. _dmtimer_add    proc    far
  194. ;
  195. ;==========================
  196. ;        Timer Add
  197. ;==========================
  198. ; Procedure:    1. Setup current timer
  199. ;               2. Hook to end of chain
  200. ;               3. Exit all done
  201. ; Entry:        [BP+6] Offset of new timer block
  202. ;               [BP+8] Segment of new timer block
  203. ; Return:       None
  204. ;
  205.  
  206. ;
  207. ; Access the stack frame
  208. ;
  209.         push    bp                      ; save c stack frame
  210.         mov     bp,sp
  211.         push    es                      ; save environment
  212.         push    ds
  213.         push    di
  214.         push    si
  215.         mov     ax,cs                   ; point to data
  216.         mov     ds,ax
  217.         mov     di,[bp+6]               ; get offset of new block
  218.         mov     dx,[bp+8]               ; get segment of new block
  219.         mov     es,dx
  220. ;
  221. ; Init the new block
  222. ;
  223.         mov     word ptr es:[di.event],0        ; no events thus far
  224.         mov     word ptr es:[di.link],0         ; no other timers right now
  225.         mov     word ptr es:[di.link+2],0
  226. ;
  227.         cmp     word ptr es:[di.ttype],0        ; interval timer?
  228.         jne     dmtimer_add_20          ; countdown if not
  229.         mov     word ptr es:[di.counter],0      ; counter is at 0
  230.         jmp     dmtimer_add_40          ; now add it to the chain
  231. ;
  232. dmtimer_add_20:
  233.         mov     ax,word ptr es:[di.interval]    ; counter set to equal interval
  234.         mov     word ptr es:[di.counter],ax
  235. ;
  236. ; Find the end of existing chain
  237. ;
  238. dmtimer_add_40:
  239.         lea     si,root_timer           ; point to the timer
  240. ;
  241. dmtimer_add_42:
  242.         mov     ax,word ptr [si.link]   ; at the null pointer?
  243.         or      ax,word ptr [si.link+2]
  244.         jz      dmtimer_add_60          ; add new to chain if so
  245.         mov     ax,word ptr [si.link+2] ; get next timer block
  246.         mov     si,word ptr [si.link]
  247.         mov     ds,ax
  248.         jmp     dmtimer_add_42          ; try again
  249. ;
  250. ; Add the new block to the chain
  251. ;
  252. dmtimer_add_60:
  253.         cli                             ; freeze the world
  254.         mov     word ptr [si.link],di   ; store location of new block
  255.         mov     word ptr [si.link+2],dx
  256.         sti                             ; alive again
  257. ;
  258. ; Exit all done
  259. ;
  260.         pop     si                      ; restore registers
  261.         pop     di
  262.         pop     ds
  263.         pop     es
  264.         pop     bp
  265.         ret
  266. ;
  267. _dmtimer_add    endp
  268.  
  269.  
  270. _dmtimer_sub    proc    far
  271. ;
  272. ;==========================
  273. ;      Timer Remove
  274. ;==========================
  275. ; Procedure:    1. Set Previous pointer to next
  276. ;               3. Exit all done
  277. ; Entry:        [BP+6] Offset of old timer block
  278. ;               [BP+8] Segment of old timer block
  279. ; Return:       AX = 0 if no error
  280. ;               AX = -1 if old timer block not in chain
  281. ;
  282.  
  283. ;
  284. ; Access the stack frame
  285. ;
  286.         push    bp                      ; save c stack frame
  287.         mov     bp,sp
  288.         push    es                      ; Save
  289.         push    ds
  290.         push    di
  291.         push    si
  292.         mov     ax,cs                   ; Access local storage
  293.         mov     ds,ax
  294.         mov     di,[bp+6]               ; get offset of old block
  295.         mov     dx,[bp+8]               ; get segment of old block
  296.         mov     es,dx
  297. ;
  298. ; Find the old pointer to block
  299. ;
  300. dmtimer_sub_40:
  301.         lea     si,root_timer           ; point to the timer
  302. ;
  303. dmtimer_sub_42:
  304.         mov     ax,word ptr [si.link]   ; get the link offset
  305.         cmp     ax,di                   ; match?
  306.         jne     dmtimer_sub_44          ; next block if not
  307.         mov     ax,word ptr [si.link+2] ; get the link segment
  308.         cmp     ax,dx                   ; match?
  309.         je      dmtimer_sub_60          ; remove old from chain if so
  310. ;
  311. dmtimer_sub_44:
  312.         mov     ax,word ptr [si.link+2] ; get next timer block
  313.         mov     si,word ptr [si.link]
  314.         cmp     ax,si                   ; are we at the end?
  315.         jne     dmtimer_sub_46          ; continue if not
  316.         or      ax,ax
  317.         jnz     dmtimer_sub_46          ; continue if not
  318.         mov     ax,-1                   ; else flag as block not found
  319.         jmp     dmtimer_sub_90
  320. ;
  321. dmtimer_sub_46:
  322.         mov     ds,ax                   ; set link segment
  323.         jmp     dmtimer_sub_42          ; try again
  324. ;
  325. ; Remove old block from the chain
  326. ;
  327. dmtimer_sub_60:
  328.         cli                             ; freeze the world
  329.         mov     ax,word ptr es:[di.link]        ; squeeze out the link
  330.         mov     word ptr [si.link],ax
  331.         mov     ax,word ptr es:[di.link+2]
  332.         mov     word ptr [si.link+2],ax
  333.         sti                             ; alive again
  334.         xor     ax,ax                   ; no errors
  335. ;
  336. ; Exit all done
  337. ;
  338. dmtimer_sub_90:
  339.         pop     si                      ; restore registers
  340.         pop     di
  341.         pop     ds
  342.         pop     es
  343.         pop     bp
  344.         ret
  345. ;
  346. _dmtimer_sub    endp
  347.  
  348.  
  349. _dmtimer_isr    proc    far
  350. ;
  351. ;==========================
  352. ;        Timer ISR
  353. ;==========================
  354. ; Procedure:     1. Test if active tick
  355. ;                2. Goto 17 if not
  356. ;                3. Get next block
  357. ;                4. Goto 17 if done
  358. ;                5. Test if interval
  359. ;                6. Goto 12 if not
  360. ;                7. Increment counter
  361. ;                8. If interval not reached goto 3
  362. ;                9. Reset counter
  363. ;               10. Increment event count
  364. ;               11. Goto xx
  365. ;               12. If event already tripped then goto 3
  366. ;               13. Countdown a tick
  367. ;               14. If not 0 then goto 3
  368. ;               15. Reset counter
  369. ;               16. Set event flag
  370. ;               17. Bump tick count
  371. ;               18. If tick count != 39 then goto 20
  372. ;               19. Reset tick count
  373. ;               20. Pass on to regular clock ISR
  374. ; Entry:        None
  375. ; Return:       None
  376. ;
  377.         push    es                      ; Save
  378.         push    ds
  379.         push    di
  380.         push    si
  381.         push    bx
  382.         push    ax
  383.         mov     ax,cs                   ; Access local storage
  384.         mov     ds,ax
  385. ;
  386. ; Restore int vector
  387. ;
  388.         lea     bx,timer_table          ; point to flag table
  389.         add     bx,timer_tick           ; add in current tick count (index)
  390.         cmp     word ptr [bx],0         ; test if this is a 1/10 sec tick
  391.         jnz     dmtimer_isr_10          ; process if so
  392.         jmp     dmtimer_isr_90          ; else exit
  393. ;
  394. ; Get the first timer block
  395. ;
  396. dmtimer_isr_10:
  397. ;
  398.         mov     ax,cs                   ; point to 1st block
  399.         mov     es,ax
  400.         lea     di,root_timer
  401.         jmp     dmtimer_isr_14
  402. ;
  403. ; Get next timer block
  404. ;
  405. dmtimer_isr_12:
  406.         mov     ax,word ptr es:[di.link+2]      ; get next block
  407.         mov     di,word ptr es:[di.link]
  408.         mov     es,ax
  409. ;
  410. ; Exit if null block
  411. ;
  412. dmtimer_isr_14:
  413.         mov     ax,es                   ; test if null block
  414.         or      ax,di
  415.         jnz     dmtimer_isr_16          ; dispatch if not
  416.         jmp     dmtimer_isr_90          ; else exit
  417. ;
  418. dmtimer_isr_16:
  419.         cmp     word ptr es:[di.ttype],0        ; is it an interval timer?
  420.         je      dmtimer_isr_20          ; process if so
  421.         jmp     dmtimer_isr_40          ; else assume countdown
  422. ;
  423. ; Process interval timer
  424. ;
  425. dmtimer_isr_20:
  426.         inc     word ptr es:[di.counter]        ; bump the counter
  427.         mov     ax,word ptr es:[di.counter]     ; test if interval reached
  428.         cmp     ax,word ptr es:[di.interval]
  429.         jnz     dmtimer_isr_12          ; next timer block if not
  430.         mov     word ptr es:[di.counter],0      ; reset the counter
  431.         inc     word ptr es:[di.event]  ; bump the event counter
  432.         jmp     dmtimer_isr_12          ; next timer block
  433. ;
  434. ; Process countdown timer
  435. ;
  436. dmtimer_isr_40:
  437.         cmp     word ptr es:[di.event],0        ; test if event already flagged
  438.         jne     dmtimer_isr_12          ; next timer block if not
  439.         dec     word ptr es:[di.counter]        ; bump the counter
  440.         jnz     dmtimer_isr_12                  ; next timer block if not expired
  441.         mov     ax,word ptr es:[di.interval]    ; reset the counter
  442.         mov     word ptr es:[di.counter],ax     ; reset the counter
  443.         inc     word ptr es:[di.event]  ; bump the event counter
  444.         jmp     dmtimer_isr_12          ; next timer block
  445. ;
  446. ; Bump counter and adjust if needed
  447. ;
  448. dmtimer_isr_90:
  449.         inc     timer_tick              ; bump timer tick counter
  450.         cmp     timer_tick,91           ; at end?
  451.         jne     dmtimer_isr_92          ; skip if not
  452.         mov     timer_tick,0            ; else reset
  453. ;
  454. ; Exit all done
  455. ;
  456. dmtimer_isr_92:
  457.         pop     ax                      ; restore registers
  458.         pop     bx
  459.         pop     si
  460.         pop     di
  461.         pop     ds
  462.         pop     es
  463.         jmp     dword ptr cs:oldint     ; pass on to regualr clock routine
  464. ;
  465. _dmtimer_isr    endp
  466.  
  467.  
  468. DMIOSEG ends
  469. END
  470.  
  471.